#include "tiles.h"

extern int G_W, G_H;

TILES::TILES(QRectF rect, TILES_TYPE new_type, QString mission, int factor, bool is_cover, CASH *cash):QObject(), QGraphicsItemGroup()
{   
    qsrand(QTime::currentTime().second());

    this->cash=cash;

    switch (new_type) {
    case TERRAIN:
        this->tiles_rect = QRectF(rect.x(), rect.y(), ((rect.width()*factor)), rect.height());
        break;

    case EDGES:
        tiles_rect = rect;
        break;

    default:
        break;
    }

    scene_rect = rect;
    type = new_type;
    this->mission = mission;
    this->is_cover = is_cover;

    is_blended = false;
    is_cover_blend_connect = false;

    vect_pix = new QVector<QPixmap*>();

    this->factor = factor;
    factor_speed = 0;

    basic_move_speed = 2;

    load_Origin();
    Generate();
    init();


    randomize();
}

void TILES::set_tiles_rect(QRectF rect)
{
    tiles_rect = rect;
}

//общая функция генерации
void TILES::Generate()
{
    switch(type){
        case TERRAIN:
            Generate_Terrain();
        break;

        case EDGES:
            Generate_Edges();
        break;
    }
}

//функция генерации земли
void TILES::Generate_Terrain()
{
//чистим старые данные
    this->childItems().clear();

//создаем временные переменные
    int x_cnt = 0, y_cnt = 0, i = 0;
    size.setX(0);
    size.setY(0);

//генерируем бекграунд
    while(x_cnt < tiles_rect.width() && y_cnt < tiles_rect.height()){
        GRAPHICS_PIXMAP_ITEM *item = new GRAPHICS_PIXMAP_ITEM(*vect_pix->at(i), this);

        item->setZValue(0);
        item->setPos(x_cnt, y_cnt);

        x_cnt += item->boundingRect().width();
        i++;

//предотвращаем вылет за пределы в массиве картинок
        if(i > vect_pix->count() - 1)
            i = 0;

//считаем кол-во тайлов в одном ряду
        if(size.y() == 0)
            size.setX(size.x() + 1);

        if(x_cnt > tiles_rect.width()){
            x_cnt = 0;
            y_cnt += item->boundingRect().height();
            size.setY(size.y() + 1);
        }
    }

    GRAPHICS_PIXMAP_ITEM *item = new GRAPHICS_PIXMAP_ITEM(*vect_pix->last());
    tile_size.setX(item->pixmap().width());
    tile_size.setY(item->pixmap().height());
}

//функция генерации краев
void TILES::Generate_Edges()
{
    this->childItems().clear();

    int cnt = 0;
    int i = 0;
    int how = 0;

    while(i < tiles_rect.height()){
        GRAPHICS_PIXMAP_ITEM *item = new GRAPHICS_PIXMAP_ITEM(*vect_pix->at(cnt), this);
        item->setZValue(0);
        item->setPos(0, item->boundingRect().height()*how);

        item = new GRAPHICS_PIXMAP_ITEM(*vect_pix->at(cnt), this);
        item->setZValue(0);

        QTransform form;
        form.rotate(180, Qt::YAxis);

        item->setTransform(form);
        item->setPos(G_W, item->boundingRect().height()*how);

        how++;
        cnt++;
        if(cnt == vect_pix->count())
            cnt = 0;

        size.setY(size.y() + 1);
        i += item->boundingRect().height();
    }

    size.setX(2);

    GRAPHICS_PIXMAP_ITEM *item = new GRAPHICS_PIXMAP_ITEM(*vect_pix->last());
    tile_size.setX(item->pixmap().width());
    tile_size.setY(item->pixmap().height());
}

//функция загрузки текстур
void TILES::load_Origin()
{
    QString str_type;

    switch (type) {
        case TERRAIN:
            str_type = "/terrain/";
        break;

        case EDGES:
            str_type = "/edges/";
        break;
    }

//находим тайлы
    QDir dir(QString(DEF_TILES_PATH + mission + str_type));

    QStringList lst_tiles(dir.entryList());
    lst_tiles.removeOne(".");
    lst_tiles.removeOne("..");

    if(lst_tiles.count() == 0){
        qDebug() << "ERROR!! folder " << DEF_TILES_PATH + mission + str_type << "   is empty!!!";
        QApplication::closeAllWindows();
    }

    vect_pix->clear();

    foreach(QString s, lst_tiles){
        vect_pix->append(cash->cash_pixmap->value("Res/tiles/" + mission + str_type + s));
    }

}

//функция инициализации тайлов
void TILES::init()
{

//репозиционирование тайла в зависимости от того, перекрывающий он или нет
    if(!is_cover)
        this->setPos(-(this->boundingRect().width()/2 - 500), 0);
    else
        this->setPos(-(this->boundingRect().width()/2 - 500), - this->boundingRect().height());

//настройка скорости анимации и глубины в сцене
    switch (type) {
    case TERRAIN:
        this->setZValue(0);
        basic_anim_speed = 4;

        break;

    case EDGES:
        this->setZValue(1);
        basic_anim_speed = 10;

        break;

    default:
        break;
    }

}

QRectF TILES::boundingRect() const
{
    return QRectF(0, 0, tile_size.x()*size.x(), tile_size.y()*size.y());
}

void TILES::set_cover(TILES *tile)
{
    this->cover = tile;
}

void TILES::set_basic_anim_speed(int value)
{
    basic_anim_speed = value;
}

void TILES::set_ActiveBlur(bool value)
{
    this->graphicsEffect()->setEnabled(value);
}

void TILES::set_time_line(QTimeLine *timeline)
{
    this->tl_bg_tiles = timeline;

//настройка временной шкалы
    connect(tl_bg_tiles, SIGNAL(valueChanged(qreal)), this, SLOT(slot_anim_forward()));
}

QPainterPath TILES::shape() const
{
    return QPainterPath();
}

void TILES::randomize()
{
    for(int i=0;i<vect_pix->count()*3;i++){

        int rand_1 = qrand()%(vect_pix->count() - 1);
        int rand_2 = qrand()%(vect_pix->count() - 1);

        QPointF tmp_pos = this->childItems().at(rand_1)->pos();
        this->childItems().at(rand_1)->setPos(this->childItems().at(rand_2)->pos());
        this->childItems().at(rand_2)->setPos(tmp_pos);
    }
}

void TILES::set_mission(QString str_mission)
{
    this->mission = str_mission;

    load_Origin();
    Generate();
    randomize();
}

//создаем переход из одного фона в другой
void TILES::create_blend(QString str_mission)
{
    connect(cover, SIGNAL(signal_invisible()), cover, SLOT(slot_blended_invis()));

    is_blended = true;

    cover->set_blend_mission(str_mission);
    blend_mission = str_mission;

    QVector<QPixmap*> *vect_pix_tmp = new QVector<QPixmap*>();

    QDir dir("Res/tiles/" + mission + "_to_" + str_mission + "/");

    QStringList lst_files = dir.entryList();
    lst_files.removeOne("..");
    lst_files.removeOne(".");

    foreach (QString str, lst_files) {
        vect_pix_tmp->append(cash->cash_pixmap->value("Res/tiles/" + mission + "_to_" + str_mission + "/" + str));
    }

    vect_blend_items = new QVector<GRAPHICS_PIXMAP_ITEM*>();

    int cnt = 0;
    int tmp_width = 0;

    while(true){
        GRAPHICS_PIXMAP_ITEM *item = new GRAPHICS_PIXMAP_ITEM(*vect_pix_tmp->at(cnt), this);
        item->setPos(tmp_width, 0);

        vect_blend_items->append(item);

        tmp_width += item->boundingRect().width();
        if(tmp_width > tiles_rect.width())
            break;

        ++cnt;
        if(cnt > vect_pix_tmp->count() - 1){
            cnt = 0;
        }
    }
}

void TILES::set_blend_mission(QString str)
{
    this->blend_mission = str;
}

TILES::~TILES()
{
}

//слот анимации тайлов
void TILES::move(MOVE_DIRECTION direction)
{
    switch (direction) {
    case LEFT:
        last_move = LEFT;
        factor_speed = basic_move_speed;
        break;

    case RIGHT:
        last_move = RIGHT;
        factor_speed = -basic_move_speed;
        break;

    default:
        break;
    }
}

void TILES::move_finish()
{
    factor_speed = 0;
}

void TILES::slot_blended_invis()
{
    is_blended = false;

    set_mission(blend_mission);

    if(blend_mission.contains("water"))
        connect(cover, SIGNAL(signal_invisible()), cover, SLOT(slot_to_water()));

    if(blend_mission.contains("city"))
        connect(cover, SIGNAL(signal_invisible()), cover, SLOT(slot_to_city()));
}

void TILES::slot_blend_to_water()
{
    disconnect(this, SIGNAL(signal_invisible()), this, SLOT(slot_blend_to_water()));
    create_blend("water");
}

void TILES::slot_blend_to_city()
{
    disconnect(this, SIGNAL(signal_invisible()), this, SLOT(slot_blend_to_city()));
    create_blend("city");
}

void TILES::slot_to_water()
{
    disconnect(this, SIGNAL(signal_invisible()), this, SLOT(slot_to_water()));
    connect(this, SIGNAL(signal_invisible()), this, SLOT(slot_cover_to_water()));

    set_mission("water");
}

void TILES::slot_to_city()
{
    disconnect(this, SIGNAL(signal_invisible()), this, SLOT(slot_to_city()));
    connect(this, SIGNAL(signal_invisible()), this, SLOT(slot_cover_to_city()));

    set_mission("city");
}

void TILES::slot_cover_to_water()
{
    disconnect(this, SIGNAL(signal_invisible()), this, SLOT(slot_cover_to_water()));

    set_mission("water");
}

void TILES::slot_cover_to_city()
{
    disconnect(this, SIGNAL(signal_invisible()), this, SLOT(slot_cover_to_city()));

    set_mission("city");
}

void TILES::slot_anim_forward()
{
    if(this->pos().y() > G_H){
        this->setPos(cover->pos().x(), cover->pos().y() - this->boundingRect().height());
        emit signal_invisible();

        return;
    }

    if(type == TERRAIN){

        this->setPos(this->pos().x() + (factor_speed*factor), this->pos().y() + basic_anim_speed);
        cover->setPos(this->pos().x() + (factor_speed*factor), cover->pos().y() + basic_anim_speed);

        if(this->pos().x() + 100 > 0 && last_move == LEFT)
            factor_speed = 0;

        if((this->pos().x() + this->boundingRect().width()) - 100 < G_W && last_move == RIGHT)
            factor_speed = 0;

    }else{
        this->setPos(0, this->pos().y() + basic_anim_speed);
        cover->setPos(0, cover->pos().y() + basic_anim_speed);
    }


}
